#ifndef SCENE_OBJ_H
#define SCENE_OBJ_H

#include "stdafx.h"

#include "RenderInterface.h"
#include "RenderType.h"
#include <string>
#include "StaticMesh.h"

using namespace std;

class RenderableSceneObject;
class DecoRenderData;
class CXmlNodeWrapper;
class GridField;

typedef enum
{
	FluidT = 0,
	SolidT = 1,
	SprayerT = 2,
	FreerT = 3,
	ArticulatedT = 4,
	AllT = 5,
	UndefinedT = 6,
} SceneObjectType;

enum DecoOpFlag
{
	OpRenderable,
	OpMovable,
	OpRotatable,
	OpSelectable,
	OpScalable,
	OpReflectable,
	OpTransparentable
};

class DecoSceneObject
{
protected:
	BOOL bIsRenderable;
	BOOL bIsMovable;
	BOOL bIsRotatable;
	BOOL bIsSelectable;
	BOOL bIsScalable;
	BOOL bIsReflectable;
	BOOL bIsTransparentable;

	INT objID;
	string name;
	SceneObjectType objType;

	//added by chenxz//
	Coords coords;
	DecoStaticMesh mesh;
	///////////////////


	//for fluid simulation//
	vector<Index3> m_associateGridIndex;
	GridField* m_grid;

public:
	DecoSceneObject(SceneObjectType type)
				  : objType(type),
				    bIsRenderable(FALSE),
					bIsMovable(FALSE),
					bIsRotatable(FALSE),
					bIsSelectable(FALSE),
					bIsScalable(FALSE),
					bIsReflectable(FALSE),
					bIsTransparentable(FALSE),
					objID(-1),
					name("undefined")
	{}
	virtual ~DecoSceneObject() {}

	BOOL CreateSceneObjectFromMesh(const std::string & path);
	BOOL CreateSceneObjectFromMesh(const DecoStaticMesh* mesh);
	void Serialize(DecoArchive& Ar) const;
	void Deserialize(DecoArchive& Ar);
	void SetAssociateGridIndex(const vector<Index3>& indices);
	void AddAssociateGridIndex(const vector<Index3>& indices);
	void ResetAssociateGridIndex();
	bool isGridCellBelongsTo(int i, int j, int k);
public:
	void SetGrid(GridField* grid)
	{
		m_grid = grid;
	}
	Coords& GetCoords()
	{
		return coords;
	}
	void SetCoords(const Coords& newCoords)
	{
		coords = newCoords;
	}
    INT GetID()const
	{
		return objID;
	}
	SceneObjectType GetType()const
	{
		return objType;
	}
	void DynamicChangeFlag(DecoOpFlag flag, BOOL value);

	BOOL IsSelectable () const
	{
		return bIsSelectable;
	}
	BOOL IsRenderable () const
	{
		return bIsRenderable;
	}
	BOOL IsMovable () const
	{
		return bIsMovable;
	}
	BOOL IsRotatable () const
	{
		return bIsRotatable;
	}
	BOOL IsReflectable () const
	{
		return bIsReflectable;
	}
	BOOL IsTransparentable () const
	{
		return bIsTransparentable;
	}

	const std::string & GetName()const
	{
		return name;
	}
	void SetName(const std::string& newname)
	{
		name = newname;
	}

	//added by chenxz//
	//inherited sceneobjs override following methods to get customized

	virtual DecoRenderData* GetRenderData()
	{
		mesh.SetLocalToWorld(coords.GetMatrix());
		return &mesh;
	};
	virtual BOOL Move(const vector3& offset);
	virtual BOOL Rotate(AXIS axis, float rad, BOOL bAlongGlobal = TRUE);
	virtual BOOL RotateAlongGlobalVector(vector3 axis, FLOAT rad);
	virtual BOOL Scale(const vector3& fac);
	virtual BOOL SetPosition(const vector3& pos);
	virtual vector3 SampleVelocity(const vector3& pos);
	virtual void Update(DOUBLE deltaTime);

	/////////////////
	
#ifdef MFC_ENABLED
public:
	//XML related operations
	virtual BOOL LoadFromXML(CXmlNodeWrapper& node);
	virtual BOOL SaveToXML(CXmlNodeWrapper& node)const;
#endif
};

#endif